﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection.Emit;

namespace Kokomo.PeInspector.Reflection.Disassembly
{
	/// <summary>
	/// Represents an instruction within a procedure.
	/// </summary>
	public class Instruction
	{
		/// <summary>
		/// Gets the starting offset of the instruction.
		/// </summary>
		public int Offset { get; private set; }
		/// <summary>
		/// Gets the op code of the instruction.
		/// </summary>
		public OpCode OpCode { get; private set; }
		/// <summary>
		/// Gets the operand of the instruction.
		/// </summary>
		public object Operand { get; private set; }
		/// <summary>
		/// Gets the length of the instruction.
		/// </summary>
		public int Length { get; private set; }
		internal int InputCount { get; private set; }
		internal int OutputCount { get; private set; }
		internal int InitialStackSize { get; private set; }

		internal Instruction(
			int offset,
			int length,
			OpCode opcode,
			//MsilRecordStackUsage[] inputUsages,
			int initialStackSize,
			int inputCount,
			int outputCount,
			object operand = null
			)
		{
			this.Offset = offset;
			this.OpCode = opcode;
			this.Length = length;
			this.Operand = operand;
			this.InitialStackSize = initialStackSize;
			this.InputCount = inputCount;
			this.OutputCount = outputCount;
		}

		public override string ToString()
		{
			string format = (this.Operand == null) ? "{0:X4}: {1}" : "{0:X4}: {1} {2}";
			string str = string.Format(format, this.Offset, this.OpCode, this.Operand);

			return str;
		}

		public int NextOffset { get { return this.Offset + this.Length; } }
	}
}
